/**
 * Created by TamTT on 1/13/14.
 * FPT University - Da Nang
 * Capstone project - group 3
 * Jornee
 */
module.exports.controller = function(app, jwt, secret, db, authentication, util, async, io, log, colors){
	var mongojs = require('mongojs');
	var gcm = require('node-gcm');

	/**
	 * Create journey - ThanhND
	 */
	app.post('/create_journey', function(req, res){
		authentication(req, function(result){
			if(result.loginStatus == 'error'){
				res.send({
					authen_status: 'error'
				});
			} else if(result.loginStatus == 'false'){
				res.send({
					authen_status: 'fail'
				});
			} else if(result.loginStatus == 'true'){
				/**
				 * Code begin
				 */
				var my_id = result.login_user;
				var journey_name = req.body.journey_name;
				var entries = eval(req.body.entries);
				var query_array = [];
				entries.forEach(function(entry){
					query_array.push(mongojs.ObjectId(entry));
				});
				var create_date = req.body.create_date;
				var type = req.body.type;
				var user_id = eval(req.body.user_id);

				db.journey.insert({
					journey_name: journey_name,
					user_id: result.login_user,
					entries: query_array,
					create_date: create_date,
					shared: {
						type: type,
						ids: user_id,
						date: new Date().toISOString()
					},
					liked: [],
					comment: [],
					modified_date: ""
				}, function(err, doc){
					if(err){
						log.error('Create journey - User %s - Error with %s'.red, my_id, err);
						res.send({
							authen_status: 'ok',
							status: 'error'
						});
					} else {
						if(type == "private"){
							db.users.update({
								username: result.login_user
							}, {
								$addToSet: {
									outside: doc._id
								}
							}, function(err){
								if(err){
									log.error('Create journey - User %s - Error with %s'.red, my_id, err);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								} else {
									log.info('Create journey - User %s - OK'.blue, my_id);
									res.send({
										authen_status: 'ok',
										status: 'ok',
										journey_id: doc._id
									});
								}
							});
						}
						if(type == "public"){
							db.users.update({
								username: result.login_user
							}, {
								$addToSet: {
									outside: doc._id
								}
							}, function(err){
								if(err){
									log.error('Create journey - User %s - Error with %s'.red, my_id, err);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								}
							});
							db.users.findOne({
								username: result.login_user
							}, function(err, user){
								if(err){
									log.error('Create journey - User %s - Error with %s'.red, my_id, err);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								}
								if(!user){
									log.warning('Create journey - User $s - No user found'.yellow, my_id);
									res.send({
										authen_status: 'ok',
										status: 'fail'
									});
								} else {
									async.each(user.follower, function(username, callback){
										db.users.update({
											username: username
										}, {
											$addToSet: {
												outside: doc._id
											}
										}, function(err){
											if(err){
												log.error('Create journey - User %s - Error with %s'.red, my_id, err);
												res.send({
													authen_status: 'ok',
													status: 'error'
												});
											}
										});
										callback();
									}, function(err){
										if(err){
											log.error('Create journey - User %s - Error with %s'.red, my_id, err);
											res.send({
												authen_status: 'ok',
												status: 'error'
											});
										} else {
											log.info('Create journey - User %s - OK'.blue, my_id);
											res.send({
												authen_status: 'ok',
												status: 'ok',
												journey_id: doc._id
											});
										}
									})
								}
							})
						}
						if(type == "specific"){
							db.users.update({
								username: result.login_user
							}, {
								$addToSet: {
									outside: doc._id
								}
							}, function(err){
								if(err){
									log.error('Create journey - User %s - Error with %s'.red, my_id, err);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								}
							});
							console.log(doc.shared.ids);
							async.each(user_id, function(username, callback){
								console.log(username);
								db.users.update({
									username: username
								}, {
									$addToSet: {
										outside: doc._id
									}
								}, function(err){
									if(err){
										log.error('Create journey - User %s - Error with %s'.red, my_id, err);
										res.send({
											authen_status: 'ok',
											status: 'error'
										});
									}
								});
								callback();
							}, function(err){
								if(err){
									log.error('Create journey - User %s - Error with %s'.red, my_id, err);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								} else {
									log.info('Create journey - User %s - OK'.blue, my_id);
									res.send({
										authen_status: 'ok',
										status: 'ok',
										journey_id: doc._id
									});
								}
							})
						}

					}
				})
			}
		});
	});

	/**
	 * Function for sending notification
	 * @param content
	 * TamTT
	 */
	function sendNoti(content){
		// with object values
		var message = new gcm.Message({
			//collapseKey: 'cms',
			delayWhileIdle: true,
			//timeToLive: 10,
			data: {
				other_id: content.other_id,
				type: content.type,
				content_id: content.content_id,
				time: content.time
			}
		});
		var sender = new gcm.Sender('AIzaSyCb-bORk00XZslcplMH3iw9eHYzaHnZav0');
		var registrationIds = [];
		db.notification.findOne({
			user_id: content.my_id
		}, {
			_id: 0,
			regId: 1
		}, function(err, getted){
			if(err){
				log.error('Send notification - User %s - Send to %s -  Result with error: %s'.red, content.other_id, content.my_id, err);
			}
			if(getted && getted.regId){
				registrationIds.push(getted.regId);
				if(registrationIds.length > 0){
					/**
					 * Params: message-literal, registrationIds-array, No. of retries, callback-function
					 **/
					sender.send(message, registrationIds, 10, function(err, result){
						if(err){
							log.error('Send notification - User %s - Send to %s -  Result with error: %s'.red, content.other_id, content.my_id, err);
						} else {
							log.info('Send notification - User %s - Send to %s - Type %s - Result %s'.blue, content.other_id, content.my_id, content.type, util.inspect(result));
						}
					});
				}
			} else {
				log.warning('Send notification - User %s - Send to %s - Type %s -  Result : No registered devices'.yellow, content.other_id, content.my_id, content.type);
			}
		});
	}

	/**
	 * Update journey - ThanhND
	 */
	app.post('/update_journey', function(req, res){
		authentication(req, function(result){
			if(result.loginStatus == 'error'){
				res.send({
					authen_status: 'error'
				});
			} else if(result.loginStatus == 'false'){
				res.send({
					authen_status: 'fail'
				});
			} else if(result.loginStatus == 'true'){
				/**
				 * Code begin
				 */
				var my_id = result.login_user;
				var journey_id = req.body.server_id;
				var journey_name = req.body.journey_name;
				var entries = eval(req.body.entries);
				var query_array = [];
				entries.forEach(function(entry){
					query_array.push(mongojs.ObjectId(entry));
				});
				var create_date = req.body.create_date;
				var type = req.body.type;
				var user_id = eval(req.body.user_id);
				var date = new Date().toISOString();

				//For notification - TamTT
				if(type && type == 'specific'){
					async.each(user_id, function(friend_id, callback){
						//Check if this action was acted before (Anti spam)
						db.notification.findOne({
							user_id: friend_id,
							'notification.other_id': my_id,
							'notification.type': 'shared',
							'notification.content_id': journey_id
						}, {
							_id: 1
						}, function(err, notification){
							if(err){
								log.error('Send notification - User %s - Send to %s - Type share - Error with %s'.red, my_id, friend_id, err);
							} else if(!notification){
								//Check if user is online, send in-app notification. If not, send system notification
								db.users.findOne({
									username: friend_id
								}, {
									_id: 0,
									chat_id: 1
								}, function(err, user){
									if(err || !user){
										if(err){
											log.error('Send notification - User %s - Send to %s - Type share - Error with %s'.red, my_id, friend_id, err);
										}
										log.warning('Send notification - User %s - Send to %s - Type share - No user found'.yellow, my_id, friend_id);
										io.sockets.socket(user.chat_id).emit('error', {
											message: 'fail'
										});
									} else {
										if(user.chat_id && user.chat_id != ''){
											//In-app notification
											log.info('Send notification - User %s - Friend %s online. Send in-app notification'.blue, my_id, friend_id);
											io.sockets.socket(user.chat_id).emit('server_noti', {
												other_id: my_id,
												type: "shared",
												content_id: journey_id,
												time: date
											});
										} else {
											//System notification
											log.info('Send notification - User %s - Friend %s offline. Send GCM notification'.blue, my_id, friend_id);
											sendNoti({
												my_id: friend_id,
												other_id: my_id,
												type: 'shared',
												content_id: journey_id,
												time: date
											});
										}
										//Update notification into database
										db.notification.update({
											user_id: friend_id
										}, {
											$push: {
												notification: {
													other_id: my_id,
													type: "shared",
													content_id: journey_id,
													time: date
												}
											},
											$inc: {
												unread_noti: 1
											}
										}, {
											upsert: true
										}, function(err){
											if(err){
												log.error('Send notification - User %s - Send to %s - Type share - Error with %s'.red, my_id, friend_id, err);
											}
											callback();
										});
									}
								});
							}
						});
					}, function(err){
						if(err){
							log.error('Update journey - User %s - Notification error with %s'.red, my_id, err);
						}
					})
				}

				db.journey.update({
					_id: mongojs.ObjectId(journey_id)
				}, {
					$set: {
						journey_name: journey_name,
						user_id: my_id,
						entries: query_array,
						create_date: create_date,
						'shared.type': type,
						'shared.date': date,
						'shared.ids': user_id,
						liked: [],
						comment: [],
						modified_date: date
					}
				}, {
					upsert: true
				}, function(err){
					if(err){
						log.error('Update journey - User %s - Error with %s'.red, my_id, err);
						res.send({
							authen_status: 'ok',
							status: 'error'
						});
					} else {
						if(type == "private"){
							db.users.update({
								username: result.login_user
							}, {
								$addToSet: {
									outside: mongojs.ObjectId(journey_id)
								}
							}, function(err){
								if(err){
									log.error('Update journey - User %s - Error with %s'.red, my_id, err);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								}
							});
							db.users.findOne({
								username: result.login_user
							}, function(err, user){
								if(err){
									log.error('Update journey - User %s - Error with %s'.red, my_id, err);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								}
								if(!user){
									log.warning('Update journey - User $s - No user found'.yellow, my_id);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								} else {
									async.each(user.follower, function(username, callback){
										db.users.update({
											username: username
										}, {
											$pull: {
												outside: mongojs.ObjectId(journey_id)
											}
										}, function(err){
											if(err){
												log.error('Update journey - User %s - Error with %s'.red, my_id, err);
												res.send({
													authen_status: 'ok',
													status: 'error'
												});
											}
										});
										callback();
									}, function(err){
										if(err){
											log.error('Update journey - User %s - Error with %s'.red, my_id, err);
											res.send({
												authen_status: 'ok',
												status: 'error'
											});
										} else {
											log.info('Update journey - User %s - OK'.blue, my_id);
											res.send({
												authen_status: 'ok',
												status: 'ok'
											});
										}
									})
								}
							})
						}
						if(type == "public"){
							db.users.update({
								username: result.login_user
							}, {
								$addToSet: {
									outside: mongojs.ObjectId(journey_id)
								}
							}, function(err){
								if(err){
									log.error('Update journey - User %s - Error with %s'.red, my_id, err);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								}
							});
							db.users.findOne({
								username: result.login_user
							}, function(err, user){
								if(err){
									log.error('Update journey - User %s - Error with %s'.red, my_id, err);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								}
								if(!user){
									log.warning('Update journey - User $s - No user found'.yellow, my_id);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								} else {
									async.each(user.follower, function(username, callback){
										db.users.update({
											username: username
										}, {
											$addToSet: {
												outside: mongojs.ObjectId(journey_id)
											}
										}, function(err){
											if(err){
												log.error('Update journey - User %s - Error with %s'.red, my_id, err);
												res.send({
													authen_status: 'ok',
													status: 'error'
												});
											}
										});
										callback();
									}, function(err){
										if(err){
											log.error('Update journey - User %s - Error with %s'.red, my_id, err);
											res.send({
												authen_status: 'ok',
												status: 'error'
											});
										} else {
											log.info('Update journey - User %s - OK'.blue, my_id);
											res.send({
												authen_status: 'ok',
												status: 'ok'
											});
										}
									})
								}
							})
						}
						if(type == "specific"){
							db.users.update({
								username: result.login_user
							}, {
								$addToSet: {
									outside: mongojs.ObjectId(journey_id)
								}
							}, function(err){
								if(err){
									log.error('Update journey - User %s - Error with %s'.red, my_id, err);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								}
							});
							db.users.findOne({
								username: result.login_user
							}, function(err, user){
								if(err){
									log.error('Update journey - User %s - Error with %s'.red, my_id, err);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								}
								if(!user){
									log.warning('Update journey - User $s - No user found'.yellow, my_id);
									res.send({
										authen_status: 'ok',
										status: 'error'
									});
								} else {
									async.each(user.follower, function(username, callback){
										db.users.update({
											username: username
										}, {
											$pull: {
												outside: mongojs.ObjectId(journey_id)
											}
										}, function(err){
											if(err){
												log.error('Update journey - User %s - Error with %s'.red, my_id, err);
												res.send({
													authen_status: 'ok',
													status: 'error'
												});
											}
										});
										callback();
									}, function(err){
										if(err){
											log.error('Update journey - User %s - Error with %s'.red, my_id, err);
											res.send({
												authen_status: 'ok',
												status: 'error'
											});
										} else {
											async.each(user_id, function(username, callback){
												db.users.update({
													username: username
												}, {
													$addToSet: {
														outside: mongojs.ObjectId(journey_id)
													}
												}, function(err){
													if(err){
														log.error('Update journey - User %s - Error with %s'.red, my_id, err);
														res.send({
															authen_status: 'ok',
															status: 'error'
														});
													}
												});
												callback();
											}, function(err){
												if(err){
													log.error('Update journey - User %s - Error with %s'.red, my_id, err);
													res.send({
														authen_status: 'ok',
														status: 'error'
													});
												} else {
													log.info('Update journey - User %s - OK'.blue, my_id);
													res.send({
														authen_status: 'ok',
														status: 'ok'
													});
												}
											})
										}
									})
								}
							})
						}
					}
				})
			}
		});
	});

	/**
	 * Delete Journey - ThanhND
	 */
	app.post('/delete_journey', function(req, res){
		authentication(req, function(result){
			if(result.loginStatus == 'error'){
				res.send({
					authen_status: 'error'
				});
			} else if(result.loginStatus == 'false'){
				res.send({
					authen_status: 'fail'
				});
			} else if(result.loginStatus == 'true'){
				/**
				 * Code begin
				 */
				var journey_id = req.body.server_id || '';
				var my_id = result.login_user;

				if(journey_id == ''){
					log.error('Delete journey - User %s - No journey id received'.red, my_id);
					res.send({
						authen_status: 'ok',
						status: 'error'
					});
				} else {
					log.info('Delete journey - User %s - Journey ID: %s'.blue, my_id, journey_id);
				}
				db.journey.remove({
					_id: mongojs.ObjectId(journey_id)
				}, function(err){
					if(err){
						log.error('Delete journey - User %s - Error with %s'.red, my_id, err);
						res.send({
							authen_status: 'ok',
							status: 'error'
						});
					} else {
						db.users.findOne({
							username: result.login_user
						}, function(err, user){
							if(err){
								log.error('Delete journey - User %s - Error with %s'.red, my_id, err);
								res.send({
									authen_status: 'ok',
									status: 'error'
								});
							}
							if(!user){
								log.warning('Delete journey - User %s - User not found'.yellow, my_id);
								res.send({
									authen_status: 'ok',
									status: 'error'
								});
							} else {
								async.each(user.follower, function(username, callback){
									db.users.update({
										username: username
									}, {
										$pull: {
											outside: mongojs.ObjectId(journey_id)
										}
									}, function(err){
										if(err){
											log.error('Delete journey - User %s - Error with %s'.red, my_id, err);
											res.send({
												authen_status: 'ok',
												status: 'error'
											});
										}
										callback();
									});
								}, function(err){
									if(err){
										log.error('Delete journey - User %s - Error with %s'.red, my_id, err);
										res.send({
											authen_status: 'ok',
											status: 'error'
										});
									} else {
										db.users.update({
											username: result.login_user
										}, {
											$pull: {
												outside: mongojs.ObjectId(journey_id)
											}
										}, function(err){
											if(err){
												log.error('Delete journey - User %s - Error with %s'.red, my_id, err);
												res.send({
													authen_status: 'ok',
													status: 'error'
												});
											} else {
												log.info('Delete journey - User %s - OK'.blue, my_id);
												res.send({
													authen_status: 'ok',
													status: 'ok'
												});
											}
										})
									}
								})
							}
						})
					}
				})
			}
		});
	});

	/**
	 * View detail journey - ThanhND
	 */
	app.post('/view_detail_journey', function(req, res){
		authentication(req, function(result){
			if(result.loginStatus == 'error'){
				res.send({
					authen_status: 'error'
				});
			} else if(result.loginStatus == 'false'){
				res.send({
					authen_status: 'fail'
				});
			} else if(result.loginStatus == 'true'){
				/**
				 * Code begin
				 */
				var my_id = result.login_user;
				var journey_id = req.body.server_id;
				db.journey.findOne({
					_id: mongojs.ObjectId(journey_id)
				}, function(err, doc1){
					if(err){
						log.error('View detail journey - User %s - Error with %s'.red, my_id, err);
						res.send({
							authen_status: 'ok',
							status: 'error'
						});
					}
					if(!doc1){
						log.warning('View detail journey - User %s - No journey'.yellow, my_id);
						res.send({
							authen_status: 'ok',
							status: 'no journey'
						});
					} else {
						db.entry.find({
							_id: {
								$in: doc1.entries
							}
						}, {
							_id: 1,
							type: 1,
							coordinate: 1,
							place_name: 1,
							address: 1,
							text: 1,
							path: 1,
							create_date: 1
						}, function(err, doc2){
							if(err){
								log.error('View detail journey - User %s - Error with %s'.red, my_id, err);
								res.send({
									authen_status: 'ok',
									status: 'error'
								});
							}
							if(!doc2){
								log.warning('View detail journey - User %s - No entry'.yellow, my_id);
								res.send({
									authen_status: 'ok',
									status: 'error'
								});
							} else {
								log.info('View detail journey - User %s - OK %s'.blue, my_id, util.inspect(doc2));
								res.send({
									authen_status: 'ok',
									status: 'ok',
									journey_name: doc1.journey_name,
									shared: doc1.shared,
									create_date: doc1.create_date,
									entries: doc2
								});
							}
						})
					}
				})
			}
		});
	});
};